home *** CD-ROM | disk | FTP | other *** search
/ Delphi Developer's Kit 1996 / Delphi Developer's Kit 1996.iso / power / acstream / aclist.pas next >
Encoding:
Pascal/Delphi Source File  |  1995-12-22  |  11.8 KB  |  537 lines

  1. unit acList;
  2.  
  3. {
  4.   Project: Non-Component Persistent Object Streaming
  5.  
  6.   Alan Ciemian
  7.   Copyright ⌐ 1995. All Rights Reserved
  8.  
  9.  
  10.   Overview
  11.   ========
  12.   Implements TacObjStringList class descended from TacStreamable.
  13.  
  14.   TacObjStringList defines a container class for TacStreamable objects.
  15.  
  16. }
  17.  
  18. interface
  19.  
  20. uses
  21.   Classes,
  22.   acStream;
  23.  
  24.  
  25. type
  26.   TacObjListIndex = Integer;  { Indexing into lists }
  27.   TacObjListCount = LongInt;  { For saving list count to stream. }
  28.  
  29. type { for TacObjStringList notifications }
  30.   TacObjListNotifyEvent = procedure (Idx: TacObjListIndex) of object;
  31.  
  32. type
  33.   TacObjStringList = class(TacStreamable)
  34.   private
  35.     FList       : TStrings;           { Ref to contained list }
  36.     FOwnList    : Boolean;            { Flag for list ownership }
  37.     FOwnObjects : Boolean;            { Flag for list item ownership }
  38.     FOnDelete   : TacObjListNotifyEvent; { Delete notification }
  39.     FOnInsert   : TacObjListNotifyEvent; { Insert notification }
  40.     procedure ResetList
  41.       (
  42.       const Strings : TStrings;
  43.       const OwnObjs : Boolean
  44.       );
  45.     procedure CloneContents(const OtherList: TacObjStringList);
  46.     procedure FreeList;
  47.     procedure FreeObjects;
  48.     { Property access methods }
  49.     function  GetCount: TacObjListIndex;
  50.   protected
  51.     { TPersistent overrides }
  52.     procedure AssignTo(Dest: TPersistent); override;
  53.     { TacStreamable overrides }
  54.     procedure InitFields; override;
  55.     procedure ReadFromStream(Stream: TacObjStream); override;
  56.     procedure SaveToStream  (Stream: TacObjStream); override;
  57.     { Protected properties }
  58.     property OnObjDelete: TacObjListNotifyEvent
  59.              read FOnDelete
  60.              write FOnDelete;
  61.     property OnObjInsert: TacObjListNotifyEvent
  62.              read FOnInsert
  63.              write FOnInsert;
  64.   public
  65.     { Construction/Destruction }
  66.     constructor Create
  67.       (
  68.       const Strings    : TStrings;
  69.       const OwnObjects : Boolean
  70.       );
  71.     destructor  Destroy; override;
  72.     { List object access }
  73.     function  AtIndex(const Idx: TacObjListIndex): TacStreamable;
  74.     function  AtName(const Name: String): TacStreamable;
  75.     { Standard list methods }
  76.     procedure BeginUpdate;
  77.     procedure EndUpdate;
  78.     function  Add(const Obj: TacStreamable): TacObjListIndex;
  79.     procedure Insert(const Idx: TacObjListIndex; const Obj: TacStreamable);
  80.     procedure Move(const FromIdx: TacObjListIndex; const ToIdx: TacObjListIndex);
  81.     { Delete's delete the objects if they are owned }
  82.     procedure DeleteIdx(const Idx: TacObjListIndex);
  83.     procedure DeleteObj(const Obj: TacStreamable);
  84.     procedure DeleteName(const Name: String);
  85.     procedure DeleteAll;
  86.     { Remove's NEVER delete the objects }
  87.     function  RemoveIdx(const Idx: TacObjListIndex): TacStreamable;
  88.     function  RemoveObj(const Obj: TacStreamable): TacStreamable;
  89.     function  RemoveName(const Name: String): TacStreamable;
  90.     { ObjStringList specific methods }
  91.     procedure UpdateObjectName(const Idx: TacObjListIndex);
  92.     { Public properties }
  93.     property Strings: TStrings
  94.              read FList;
  95.     property Count: TacObjListIndex
  96.              read GetCount;
  97.     property OwnObjects: Boolean
  98.              read FOwnObjects
  99.              write FOwnObjects;
  100.     property OwnList: Boolean
  101.              read FOwnList
  102.              write FOwnList;
  103.   end;
  104.  
  105.  
  106. implementation
  107.  
  108.  
  109. { TacObjStringList }
  110.  
  111.  
  112. {
  113. Create creates a TacObjStringList tied to a specified TStrings instance.
  114. If Strings parameter is nil, a new TStringList will be created.
  115. If OwnObjects parameter is True, list will have responsibility for
  116.   deleting contained objects.
  117. }
  118. constructor TacObjStringList.Create
  119.   (
  120.   const Strings:    TStrings;
  121.   const OwnObjects: Boolean
  122.   );
  123. begin
  124.   inherited Create;
  125.   ResetList(Strings, OwnObjects);
  126. end;
  127.  
  128.  
  129. {
  130. Destroy frees the contained objects if they are owned and
  131.   frees the list if it is owned.
  132. }
  133. destructor  TacObjStringList.Destroy;
  134. begin
  135.   FreeList;
  136.   inherited Destroy;
  137. end;
  138.  
  139.  
  140. {
  141. InitFields sets default values for member fields.
  142. }
  143. procedure TacObjStringList.InitFields;
  144. begin
  145.   inherited InitFields;
  146.   FList       := nil;
  147.   FOwnList    := False;
  148.   FOwnObjects := False;
  149. end;
  150.  
  151.  
  152. {
  153. AssignTo override allows assignment of TacObjStringList instances.
  154. Destination list will be reset to contain and own copies of the items
  155.   currently in this list. The destination instance list and list
  156.   ownership will not otherwise be changed.
  157. }
  158. procedure TacObjStringList.AssignTo
  159.   (
  160.   Dest : TPersistent
  161.   );
  162. var
  163.   DestStringList : TacObjStringList;
  164. begin
  165.   if ( Dest = self ) then Exit;
  166.  
  167.   if ( (Dest is TacObjStringList) and (Self is Dest.ClassType) ) then
  168.     begin  { Assigning to same or superclass }
  169.     DestStringList := ( Dest as TacObjStringList );
  170.     DestStringList.ResetList(DestStringList.FList, True);
  171.     DestStringList.CloneContents(self);
  172.     end
  173.   else
  174.     begin  { TPersistent will process error }
  175.     inherited AssignTo(Dest);
  176.     end;
  177. end;
  178.  
  179.  
  180. {
  181. ResetList sets the contained list and ownership flag.
  182. If the Strings parameter is nil a new TStringList is created.
  183. If the Strings parameter is assigned it becomes the contained list
  184.   and it is emptied.
  185. }
  186. procedure TacObjStringList.ResetList
  187.   (
  188.   const Strings : TStrings;
  189.   const OwnObjs : Boolean
  190.   );
  191. begin
  192.   { If changing list, free current list }
  193.   if ( Strings <> FList ) then FreeList;
  194.  
  195.   if ( Assigned(Strings) ) then
  196.     begin
  197.     FList := Strings;
  198.     end
  199.   else
  200.     begin { Create a new list }
  201.     FList := TStringList.Create;
  202.     FOwnList := True;
  203.     end;
  204.   DeleteAll;
  205.   OwnObjects := OwnObjs;
  206. end;
  207.  
  208.  
  209. {
  210. CloneContents clones all the items in another list and adds them to this list.
  211. }
  212. procedure TacObjStringList.CloneContents
  213.   (
  214.   const OtherList: TacObjStringList
  215.   );
  216. var
  217.   Idx       : TacObjListIndex;
  218.   Item      : TacStreamable;
  219.   ItemClass : TacStreamableClass;
  220. begin
  221.   for Idx := 0 to (OtherList.Count - 1) do
  222.     begin
  223.     Item      := OtherList.AtIndex(Idx);
  224.     ItemClass := TacStreamableClass(Item.ClassType);
  225.     Add(ItemClass.CreateClone(Item));
  226.     end;
  227. end;
  228.  
  229.  
  230. {
  231. FreeList frees the list reference
  232. }
  233. procedure TacObjStringList.FreeList;
  234. begin
  235.   if ( Assigned(FList) ) then
  236.     begin
  237.     if ( FOwnObjects ) then FreeObjects;
  238.     if ( FOwnList    ) then
  239.       begin
  240.       FList.Free;
  241.       FList := nil;
  242.       end;
  243.     end;
  244. end;
  245.  
  246.  
  247. {
  248. FreeObjects frees all the objects in the list.
  249. }
  250. procedure TacObjStringList.FreeObjects;
  251. var
  252.   Idx : TacObjListIndex;
  253. begin
  254.   for Idx := 0 to (Count - 1) do
  255.     begin
  256.     AtIndex(Idx).Free;
  257.     end;
  258. end;
  259.  
  260.  
  261. {
  262. ReadFromStream override resets the list and fills it from a stream image.
  263. }
  264. procedure TacObjStringList.ReadFromStream
  265.   (
  266.   Stream : TacObjStream
  267.   );
  268. var
  269.   ReadCount : TacObjListCount;
  270.   ReadIdx   : TacObjListIndex;
  271. begin
  272.   { Clear or create the list reference as needed }
  273.   ResetList(FList, True);
  274.  
  275.   { Read contained object count }
  276.   Stream.ReadBuffer(ReadCount, sizeof(ReadCount));
  277.   { Read objects }
  278.   for ReadIdx := 1 to ReadCount do
  279.     begin
  280.     Add(Stream.ReadObject(nil));
  281.     end;
  282. end;
  283.  
  284.  
  285. {
  286. SaveToStream override saves an image of the list to a stream.
  287. }
  288. procedure TacObjStringList.SaveToStream
  289.   (
  290.   Stream : TacObjStream
  291.   );
  292. var
  293.   SaveCount : TacObjListCount;
  294.   SaveIdx   : TacObjListIndex;
  295. begin
  296.   { Save contained object count }
  297.   SaveCount := Count;
  298.   Stream.SaveBuffer(SaveCount, Sizeof(SaveCount));
  299.   { Save objects }
  300.   for SaveIdx := 0 to (SaveCount - 1) do
  301.     begin
  302.     Stream.SaveObject(AtIndex(SaveIdx));
  303.     end;
  304. end;
  305.  
  306.  
  307. {
  308. AtIndex returns a reference to the object at a specific index.
  309. }
  310. function  TacObjStringList.AtIndex
  311.   (
  312.   const Idx : TacObjListIndex
  313.   ): TacStreamable;
  314. begin
  315.   Result := nil;
  316.   if ( (0 <= Idx) and (Idx < Count) ) then
  317.     begin
  318.     Result := FList.Objects[Idx] as TacStreamable;
  319.     end;
  320. end;
  321.  
  322.  
  323. {
  324. AtName returns a reference to the object with a specific name.
  325. }
  326. function  TacObjStringList.AtName
  327.   (
  328.   const Name : String
  329.   ): TacStreamable;
  330. begin
  331.   Result := AtIndex(FList.IndexOf(Name));
  332. end;
  333.  
  334.  
  335. procedure TacObjStringList.BeginUpdate;
  336. begin
  337.   FList.BeginUpdate;
  338. end;
  339.  
  340.  
  341. procedure TacObjStringList.EndUpdate;
  342. begin
  343.   FList.EndUpdate;
  344. end;
  345.  
  346.  
  347. {
  348. Add adds an object to the list.
  349. If Obj is added the OnInsert notification is fired.
  350. }
  351. function  TacObjStringList.Add
  352.   (
  353.   const Obj : TacStreamable
  354.   ): TacObjListIndex;
  355. var
  356.   AddIdx : TacObjListIndex;
  357. begin
  358.   Result := -1;
  359.   if ( Assigned(Obj) ) then
  360.     begin
  361.     Result := FList.AddObject(Obj.AsString, Obj);
  362.     { Call notify event }
  363.     if ( Assigned(FOnInsert) ) then FOnInsert(Result);
  364.     end;
  365. end;
  366.  
  367.  
  368. {
  369. Inserts adds an object to the list at a specified position.
  370. If Obj is added the OnInsert notification is fired.
  371. }
  372. procedure TacObjStringList.Insert
  373.   (
  374.   const Idx : TacObjListIndex;
  375.   const Obj : TacStreamable
  376.   );
  377. begin
  378.   if ( Assigned(Obj) ) then
  379.     begin
  380.     FList.InsertObject(Idx, Obj.AsString, Obj);
  381.     { Call notify event }
  382.     if ( Assigned(FOnInsert) ) then FOnInsert(Idx);
  383.     end;
  384. end;
  385.  
  386.  
  387. {
  388. Move moves a list object from one index to another.
  389. }
  390. procedure TacObjStringList.Move
  391.   (
  392.   const FromIdx : TacObjListIndex;
  393.   const ToIdx   : TacObjListIndex
  394.   );
  395. begin
  396.   FList.Move(FromIdx, ToIdx);
  397. end;
  398.  
  399.  
  400. {
  401. DeleteIdx
  402. Removes the object at the specified index from the list and deletes it.
  403. If an object is found at the index:
  404.   The OnDelete notification is fired.
  405.   The Object is removed from the list.
  406.   The Object is freed if the list owns the objects.
  407. }
  408. procedure TacObjStringList.DeleteIdx
  409.   (
  410.   const Idx : TacObjListIndex
  411.   );
  412. var
  413.   Obj : TacStreamable;
  414. begin
  415.   Obj := AtIndex(Idx);
  416.  
  417.   if ( Assigned(Obj) ) then
  418.     begin
  419.     { Call delete notify event }
  420.     if ( Assigned(FOnDelete) ) then FOnDelete(Idx);
  421.  
  422.     { Delete object if owned }
  423.     if ( FOwnObjects ) then Obj.Free;
  424.     end;
  425.  
  426.   { Remove item from list }
  427.   FList.Delete(Idx);
  428. end;
  429.  
  430.  
  431. {
  432. DeleteObj
  433. Removes the specified object from the list and deletes it.
  434. Looks up the index of the object and forwards to DeleteIdx.
  435. }
  436. procedure TacObjStringList.DeleteObj
  437.   (
  438.   const Obj : TacStreamable
  439.   );
  440. begin
  441.   DeleteIdx(FList.IndexOfObject(Obj));
  442. end;
  443.  
  444.  
  445. {
  446. DeleteName
  447. Removes the object with the specified name from the list and deletes it.
  448. Looks up the index of the name and forwards to DeleteIdx.
  449. }
  450. procedure TacObjStringList.DeleteName
  451.   (
  452.   const Name : String
  453.   );
  454. begin
  455.   DeleteIdx(FList.IndexOf(Name));
  456. end;
  457.  
  458.  
  459. {
  460. DeleteAll
  461. Removes all objects from the list and deletes them.
  462. }
  463. procedure TacObjStringList.DeleteAll;
  464. var
  465.   Idx : TacObjListIndex;
  466. begin
  467.   for Idx := (Count - 1) downto 0 do
  468.     begin
  469.     DeleteIdx(Idx);
  470.     end;
  471. end;
  472.  
  473.  
  474. {
  475. RemoveIdx
  476. Removes and returns the object at the specified index.
  477. }
  478. function  TacObjStringList.RemoveIdx
  479.   (
  480.   const Idx : TacObjListIndex
  481.   ): TacStreamable;
  482. begin
  483.   Result := AtIndex(Idx);
  484.   FList.Delete(Idx);
  485. end;
  486.  
  487.  
  488. {
  489. RemoveObj
  490. Removes and returns the specified object.
  491. }
  492. function  TacObjStringList.RemoveObj
  493.   (
  494.   const Obj : TacStreamable
  495.   ): TacStreamable;
  496. begin
  497.   RemoveIdx(FList.IndexOfObject(Obj));
  498. end;
  499.  
  500.  
  501. {
  502. RemoveName
  503. Removes and returns the object with the specified name.
  504. }
  505. function  TacObjStringList.RemoveName
  506.   (
  507.   const Name : String
  508.   ): TacStreamable;
  509. begin
  510.   RemoveIdx(FList.IndexOf(Name));
  511. end;
  512.  
  513.  
  514. {
  515. UpdateObjectName allows the object at a specified index to update its
  516.   reference name in the list.
  517. }
  518. procedure TacObjStringList.UpdateObjectName
  519.   (
  520.   const Idx : TacObjListIndex
  521.   );
  522. begin
  523.   FList.Strings[Idx] := AtIndex(Idx).AsString;
  524. end;
  525.  
  526.  
  527. {
  528. GetCount returns the number of objects in the list.
  529. }
  530. function  TacObjStringList.GetCount: TacObjListIndex;
  531. begin
  532.   Result := FList.Count;
  533. end;
  534.  
  535.  
  536. end.
  537.